import { _decorator, AnimationClip, AnimationComponent, Component, Animation, SpriteFrame } from 'cc';
import { ENTITY_STATE_ENUM, FSM_PARAMS_TYPE_ENUM, PARAMS_NAME_ENUM } from '../../Enums';
import { State } from '../../Base/State';
import { StateMachine, getInitParamsTrigger, getInitParamsNumber } from '../../Base/StateMachine';
import IdleSubStateMachine from './IdleSubStateMachine';
import TurnLeftSubStateMachine from './TurnLeftSubStateMachine';
import TurnRightSubStateMachine from './TurnRightSubStateMachine';
import BlockFrontSubStateMachine from './BlockFrontSubStateMachine';
import { EntityManager } from '../../Base/EntityManager';
import BlockLeftSubStateMachine from './BlockLeftSubStateMachine';
import BlockTurnLeftSubStateMachine from './BlockTurnLeftSubStateMachine';
import BlockTurnRightSubStateMachine from './BlockTurnRightSubStateMachine';
import BlockBackSubStateMachine from './BlockBackSubStateMachine';
import BlockRightSubStateMachine from './BlockRightSubStateMachine';
import DeathSubStateMachine from './DeathSubStateMachine';
import AirDeathSubStateMachine from './AirDeathSubStateMachine';
import AttachSubStateMachine from './AttachSubStateMachine';
const { ccclass, property } = _decorator;

type ParamsValueType = boolean | number;

export interface IParamsValue {
    type: FSM_PARAMS_TYPE_ENUM;
    value: ParamsValueType;
}

@ccclass('PlayerStateMachine')
export class PlayerStateMachine extends StateMachine {

    async init() {
        this.animationComponent = this.addComponent(Animation);

        this.initParams();
        this.initStateMachines();
        this.initAnimationEvent();

        await Promise.all(this.waitingList);
    }

    initParams() {
        this.params.set(PARAMS_NAME_ENUM.IDLE, getInitParamsTrigger());
        this.params.set(PARAMS_NAME_ENUM.TURN_LEFT, getInitParamsTrigger());
        this.params.set(PARAMS_NAME_ENUM.TURN_RIGHT, getInitParamsTrigger());
        this.params.set(PARAMS_NAME_ENUM.BLOCK_TURN_LEFT, getInitParamsTrigger());
        this.params.set(PARAMS_NAME_ENUM.BLOCK_TURN_RIGHT, getInitParamsTrigger());
        this.params.set(PARAMS_NAME_ENUM.BLOCK_FRONT, getInitParamsTrigger());
        this.params.set(PARAMS_NAME_ENUM.BLOCK_BACK, getInitParamsTrigger());
        this.params.set(PARAMS_NAME_ENUM.BLOCK_RIGHT, getInitParamsTrigger());
        this.params.set(PARAMS_NAME_ENUM.BLOCK_LEFT, getInitParamsTrigger());
        this.params.set(PARAMS_NAME_ENUM.DEATH, getInitParamsTrigger());
        this.params.set(PARAMS_NAME_ENUM.AIR_DEATH, getInitParamsTrigger());
        this.params.set(PARAMS_NAME_ENUM.ATTACH, getInitParamsTrigger());
        this.params.set(PARAMS_NAME_ENUM.DIRECTION, getInitParamsNumber());
    }

    initStateMachines() {
        this.stateMachines.set(PARAMS_NAME_ENUM.IDLE, new IdleSubStateMachine(this));
        this.stateMachines.set(PARAMS_NAME_ENUM.TURN_LEFT, new TurnLeftSubStateMachine(this));
        this.stateMachines.set(PARAMS_NAME_ENUM.TURN_RIGHT, new TurnRightSubStateMachine(this));
        this.stateMachines.set(PARAMS_NAME_ENUM.BLOCK_FRONT, new BlockFrontSubStateMachine(this));
        this.stateMachines.set(PARAMS_NAME_ENUM.BLOCK_BACK, new BlockBackSubStateMachine(this));
        this.stateMachines.set(PARAMS_NAME_ENUM.BLOCK_RIGHT, new BlockRightSubStateMachine(this));
        this.stateMachines.set(PARAMS_NAME_ENUM.BLOCK_LEFT, new BlockLeftSubStateMachine(this));
        this.stateMachines.set(PARAMS_NAME_ENUM.BLOCK_TURN_LEFT, new BlockTurnLeftSubStateMachine(this));
        this.stateMachines.set(PARAMS_NAME_ENUM.BLOCK_TURN_RIGHT, new BlockTurnRightSubStateMachine(this));
        this.stateMachines.set(PARAMS_NAME_ENUM.DEATH, new DeathSubStateMachine(this));
        this.stateMachines.set(PARAMS_NAME_ENUM.AIR_DEATH, new AirDeathSubStateMachine(this));
        this.stateMachines.set(PARAMS_NAME_ENUM.ATTACH, new AttachSubStateMachine(this));
    }

    run() {
        switch (this.currentState) {
            case this.stateMachines.get(PARAMS_NAME_ENUM.IDLE):
            case this.stateMachines.get(PARAMS_NAME_ENUM.TURN_LEFT):
            case this.stateMachines.get(PARAMS_NAME_ENUM.TURN_RIGHT):
            case this.stateMachines.get(PARAMS_NAME_ENUM.BLOCK_FRONT):
            case this.stateMachines.get(PARAMS_NAME_ENUM.BLOCK_BACK):
            case this.stateMachines.get(PARAMS_NAME_ENUM.BLOCK_LEFT):
            case this.stateMachines.get(PARAMS_NAME_ENUM.BLOCK_RIGHT):
            case this.stateMachines.get(PARAMS_NAME_ENUM.BLOCK_TURN_LEFT):
            case this.stateMachines.get(PARAMS_NAME_ENUM.BLOCK_TURN_RIGHT):
            case this.stateMachines.get(PARAMS_NAME_ENUM.DEATH):
            case this.stateMachines.get(PARAMS_NAME_ENUM.AIR_DEATH):
            case this.stateMachines.get(PARAMS_NAME_ENUM.ATTACH):
                if (this.params.get(PARAMS_NAME_ENUM.BLOCK_FRONT).value) {
                    this.currentState = this.stateMachines.get(PARAMS_NAME_ENUM.BLOCK_FRONT);
                } else if (this.params.get(PARAMS_NAME_ENUM.BLOCK_TURN_LEFT).value) {
                    this.currentState = this.stateMachines.get(PARAMS_NAME_ENUM.BLOCK_TURN_LEFT);
                } else if (this.params.get(PARAMS_NAME_ENUM.TURN_LEFT).value) {
                    this.currentState = this.stateMachines.get(PARAMS_NAME_ENUM.TURN_LEFT);
                } else if (this.params.get(PARAMS_NAME_ENUM.IDLE).value) {
                    this.currentState = this.stateMachines.get(PARAMS_NAME_ENUM.IDLE);
                } else if (this.params.get(PARAMS_NAME_ENUM.TURN_RIGHT).value) {
                    this.currentState = this.stateMachines.get(PARAMS_NAME_ENUM.TURN_RIGHT);
                } else if (this.params.get(PARAMS_NAME_ENUM.BLOCK_BACK).value) {
                    this.currentState = this.stateMachines.get(PARAMS_NAME_ENUM.BLOCK_BACK);
                } else if (this.params.get(PARAMS_NAME_ENUM.BLOCK_LEFT).value) {
                    this.currentState = this.stateMachines.get(PARAMS_NAME_ENUM.BLOCK_LEFT);
                } else if (this.params.get(PARAMS_NAME_ENUM.BLOCK_RIGHT).value) {
                    this.currentState = this.stateMachines.get(PARAMS_NAME_ENUM.BLOCK_RIGHT);
                } else if (this.params.get(PARAMS_NAME_ENUM.BLOCK_TURN_RIGHT).value) {
                    this.currentState = this.stateMachines.get(PARAMS_NAME_ENUM.BLOCK_TURN_RIGHT);
                } else if (this.params.get(PARAMS_NAME_ENUM.DEATH).value) {
                    this.currentState = this.stateMachines.get(PARAMS_NAME_ENUM.DEATH);
                } else if (this.params.get(PARAMS_NAME_ENUM.AIR_DEATH).value) {
                    this.currentState = this.stateMachines.get(PARAMS_NAME_ENUM.AIR_DEATH);
                } else if (this.params.get(PARAMS_NAME_ENUM.ATTACH).value) {
                    this.currentState = this.stateMachines.get(PARAMS_NAME_ENUM.ATTACH);
                } else {
                    this.currentState = this.currentState;
                }
                break;
            default:
                this.currentState = this.stateMachines.get(PARAMS_NAME_ENUM.IDLE);
                break;
        }
    }

    initAnimationEvent() {
        this.animationComponent.on(Animation.EventType.FINISHED, () => {
            const name = this.animationComponent.defaultClip.name;
            const whiteList = ['turn', 'block', 'attach'];
            if (whiteList.some(v => name.includes(v))) {
                this.node.getComponent(EntityManager).state = ENTITY_STATE_ENUM.IDLE;
            }
        });
    }
}

